#pragma once
#include <vector>
using namespace std;



/**
* This class provides support for the denormalization process while
* reading a 3D content file. Editors commonly only reserve one vertex with
* multiple texcoord & normal data. A VertexBuffer however requires that the
* that one vertex with for example 3 different texcoords & normals be converted
* to 3 rows with the vertex , texcoord & normal data.
* 
* A vector with VertexIndexSupport needs to be searched quickly, so this class
* provides support for binary search.
*
* @author Koen Samyn
*/
class VertexIndexSupport
{
public:
	/**
	* Creates a new VertexIndexSupport object. This default constructor provides
	* support for 3 indices : vertex index, normal index & texcoord index in that
	* order.
	* @param size the number of indices in the vector.
	*/
	VertexIndexSupport(int size);
	/**
	* Destroys the VertexIndexSupport object.
	*/ 
	virtual ~VertexIndexSupport(void);
	/**
	* Sets a semantic index value in this object.
	* @param index the index in the internal array.
	* @param indexValue the value to set.
	* @return true if setting the value was succesful, false otherwise.
	*/
	virtual bool SetSemanticIndex(unsigned short index, unsigned short indexValue);
	/**
	* Gets the value of an index.
	* @param index the index to get the semantic index for.
	*/ 
	virtual unsigned short GetSemanticIndex(unsigned short index);
	/**
	* Sets the id of this vertex in the vertex buffer
	* @param idInVertexBuffer the id in the vertexbuffer.
	*/
	void SetIdInVertexBuffer(int idInVertexBuffer){
		m_IdInVertexBuffer = idInVertexBuffer;
	}

	/**
	* Gets the id of this vertex in the vertex buffer.
	* @return the id of this vertex in the vertexbuffer.
	*/
	unsigned short GetIdInVertexBuffer(){
		return m_IdInVertexBuffer;
	}
	
	/**
	* Compares this VertexIndexSupport object with another VertexIndexSupport object.
	* @param toCompare the VertexIndexSupport object to compare to.
	* @return true if this VertexIndexSupport object is before the toCompare VertexIndexSupport object.
	*/
	bool operator<(const VertexIndexSupport& toCompare)const;

	/**
	* Compares this VertexIndexSupport object with another VertexIndexSupport object.
	* @param toCompare the VertexIndexSupport object to compare to.
	* @return true if this VertexIndexSupport object equals the other VertexIndexSupport object.
	*/
	bool Equals(VertexIndexSupport* toCompare) const;

	/**
	* Calculates a hash function for this vertex index support object
	* @return a hash 
	*/
	size_t hash() const;

private:
	/**
	* The vector with the indices.
	*/
	vector<unsigned short> m_Indices;
	/**
	* The id in the indexbuffer
	*/ 
	unsigned short m_IdInVertexBuffer;

	friend struct VertexIndexSupportSorter;
};

struct VertexIndexSupportSorter
{
public:
	/*
	* Functor for sorting.
	* @param a the first object to compare.
	* @param b the second object to compare.
	* @return true if the first object is before the second object.
	*/
	bool operator()(VertexIndexSupport const* a, VertexIndexSupport const* b) const{
		vector<unsigned short>::const_iterator itThis,itToCompare;
	for ( itThis = a->m_Indices.begin(), itToCompare = b->m_Indices.begin();
		itThis != a->m_Indices.end() && itToCompare != b->m_Indices.end();
		++itThis, ++itToCompare)
	{
		unsigned short thisIndex = *itThis;
		unsigned short toCompareIndex = *itToCompare;
		if (thisIndex < toCompareIndex)
			return true;
		else if (thisIndex > toCompareIndex)
			return false;
	}
	
	return false;
	}
};